home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / ethrax25 / ax25util.c < prev    next >
C/C++ Source or Header  |  1994-05-30  |  9KB  |  306 lines

  1. /*
  2. **  AX25UTIL.C - utility routines for Ether to AX.25 packet driver
  3. **  Copyright (C) 1994  Gary L. Grebus
  4. **
  5. **  This program is free software; you can redistribute it and/or modify
  6. **  it under the terms of the GNU General Public License as published by
  7. **  the Free Software Foundation; version 2.
  8. **
  9. **  This program is distributed in the hope that it will be useful,
  10. **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. **  GNU General Public License for more details.
  13. **
  14. **  You should have received a copy of the GNU General Public License
  15. **  along with this program; if not, write to the Free Software
  16. **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. **
  18. **
  19. ** Utilities for handling AX.25 addresses encoded into a form that 
  20. ** resembles an Ethernet address.
  21. **
  22. ** An AX.25 address consists of 7 octets in the "shifted" form described
  23. ** in the AX.25 spec.
  24. **
  25. ** The psuedo-Ethernet form consists six bytes:
  26. **     The low order byte is contains the SSID, in the AX.25 left-shifted
  27. **        form (this insures the address is not a broadcast address).
  28. **     The next two bytes contain the first two bytes of the AX.25
  29. **        address in AX.25 left-shifted from.
  30. **     The last 3 bytes contain the final 4 bytes AX.25 address ,
  31. **        encoded using 6 bit characters (0-9, blank, A-Z). 
  32. **
  33. ** The AX.25 address QST-0 is interpreted as the broadcast address and
  34. ** is converted to the pseudo-ethernet address FF-FF-FF-FF-FF-FF, and
  35. ** vice versa.
  36. **
  37. ** Original version:
  38. **    7 April 1994 - Gary L. Grebus, K8LT, glg@k8lt.ampr.org
  39. */
  40.  
  41. #ifndef DRIVER
  42. #include <ctype.h>
  43. #include <stdlib.h>
  44. #endif
  45.  
  46. #define ARP_REQUEST 0x0100                /* ARP request opcode */
  47. #define ARP_REPLY 0x0200                  /* ARP reply opcode */
  48.  
  49. #include "ax25util.h"
  50. #define SSID 0x1e                        /* Mask for SSID bits in AX.25 addr */
  51.  
  52. typedef struct _AX25Arp {
  53.         int hardware;                       /* Hardware type */
  54.     int protocol;                       /* Protocol type */
  55.     char hwalen;                        /* Hardware addr length in bytes */
  56.     char pralen;                        /* Protocol addr length in bytes */
  57.     int  opcode;                        /* ARP opcode */
  58.     unsigned char shwaddr[AXALEN];      /* Sender hardware address */
  59.     long sprotoaddr;                    /* Sender protocol address */
  60.         unsigned char thwaddr[AXALEN];      /* Target hardware address */
  61.         long tprotoaddr;                    /* Target protocol address */
  62. } AX25Arp;
  63.  
  64. typedef struct _EtherArp {
  65.     int hardware;                       /* Hardware type */
  66.     int protocol;                       /* Protocol type */
  67.     char hwalen;                        /* Hardware addr length in bytes */
  68.     char pralen;                        /* Protocol addr length in bytes */
  69.     int  opcode;                        /* ARP opcode */
  70.     char shwaddr[PSEUDOLEN];            /* Sender hardware address */
  71.     long sprotoaddr;                    /* Sender protocol address */
  72.     char thwaddr[PSEUDOLEN];            /* Target hardware address */
  73.     long tprotoaddr;                    /* Target protocol address */
  74. } EtherArp;
  75.  
  76. char qst[] = { 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '\0'<<1 };
  77.  
  78. /* A six-bit encoding of the AX.25 characters: 0-9, A-Z, space */
  79. /* Invalid characters mapped to 63 */
  80. unsigned char sixbit[] = {
  81.       37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  82.       37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  83.     36,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
  84.     0,1,2,3,4,5,6,7,8,9,37,37,37,37,37,37,
  85.     37,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
  86.     25,26,27,28,29,30,31,32,33,34,35,37,37,37,37,37};
  87.   
  88. unsigned char eightbit[] = {
  89.       '0'<<1, '1'<<1, '2'<<1, '3'<<1, '4'<<1, '5'<<1, '6'<<1, '7'<<1,
  90.     '8'<<1, '9'<<1,
  91.     'A'<<1, 'B'<<1, 'C'<<1, 'D'<<1, 'E'<<1, 'F'<<1, 'G'<<1, 'H'<<1,
  92.     'I'<<1, 'J'<<1, 'K'<<1, 'L'<<1, 'M'<<1, 'N'<<1, 'O'<<1, 'P'<<1,
  93.     'Q'<<1, 'R'<<1, 'S'<<1, 'T'<<1, 'U'<<1, 'V'<<1, 'W'<<1, 'X'<<1,
  94.     'Y'<<1, 'Z'<<1, ' '<<1, '?'<<1 };
  95.  
  96. /* Routine to convert an ARP packet containing AX.25 addresses to the
  97.  * equivalent packet containing pseudo-Ethernet addresses.
  98.  * Since the packet will shrink, do the conversion such that it could be
  99.  * happening in-place.
  100.  */
  101. void
  102. AArpToEArp(AX25Arp far *a_arp, EtherArp far *e_arp)
  103. {
  104.     int i;
  105.  
  106.     e_arp->hardware = 0x0100;
  107.     e_arp->protocol = 0x0008;
  108.     e_arp->hwalen = 6;
  109.     e_arp->pralen = 4;
  110.     e_arp->opcode = a_arp->opcode;
  111.     a_arp->shwaddr[6] &= SSID;        /* Turn off any AX.25 control bits */
  112.     AX25ToEther(&(a_arp->shwaddr[0]), (ether_t *)&(e_arp->shwaddr[0]));
  113.     e_arp->sprotoaddr = a_arp->sprotoaddr;
  114.     if( a_arp->opcode == ARP_REPLY ) {
  115.     a_arp->thwaddr[6] &= SSID;        /* Turn off any AX.25 control bits */
  116.         AX25ToEther(&(a_arp->thwaddr[0]), (ether_t *)&(e_arp->thwaddr[0]));
  117.     } else {
  118.     for( i = 0; i < PSEUDOLEN; i++)
  119.         e_arp->thwaddr[i] = '\0';
  120.     }
  121.     e_arp->tprotoaddr = a_arp->tprotoaddr;
  122. }
  123.  
  124. /* Convert an AX.25 address in network form into a pseudo-ethernet address */
  125. void
  126. AX25ToEther(unsigned char far *ax25, ether_t *ether)
  127. {
  128.     register int i;
  129.  
  130.     for(i = 0; i < AXALEN; i++) {
  131.         if( ax25[i] != qst[i] )
  132.             break;
  133.     }
  134.     if (i == AXALEN) {
  135.         for( i = 0; i < PSEUDOLEN; i++)
  136.             *ether++ = (unsigned char)0xff;
  137.  
  138.     return;
  139.     }
  140.  
  141.     /* Do this in reverse order to allow the source and destination
  142.      * to be the same buffer.
  143.      */
  144.     ether[5] = (sixbit[ ax25[4] >> 1 ] << 6) | 
  145.            sixbit[ ax25[5] >> 1 ];
  146.  
  147.     ether[4] = (sixbit[ ax25[3] >> 1 ] << 4) |
  148.            (sixbit[ ax25[4] >> 1 ] >> 2);
  149.  
  150.     ether[3] = (sixbit[ ax25[2] >> 1 ] << 2)  |
  151.            (sixbit[ ax25[3] >> 1 ] >> 4);
  152.  
  153.     ether[2] = ax25[1];
  154.     ether[1] = ax25[0];
  155.     ether[0] = ax25[6] & SSID;
  156.     
  157. }
  158.  
  159. /* Routine to convert an ARP packet containing pseudo-Ethernet addresses
  160.  * to the equivalent packet containing AX.25 addresses.
  161.  *
  162.  * This routine assumes that the constant fields of the AX.25 ARP packet
  163.  * have been statically initialized.
  164.  */
  165. void
  166. EArpToAArp(EtherArp far *e_arp, AX25Arp *a_arp)
  167. {
  168.     int i;
  169.  
  170.     a_arp->opcode = e_arp->opcode;
  171.  
  172.      EtherToAX25((ether_t *)&(e_arp->shwaddr[0]), &(a_arp->shwaddr[0]));
  173.      a_arp->sprotoaddr = e_arp->sprotoaddr;
  174.  
  175.     if( e_arp->opcode == ARP_REPLY )
  176.         EtherToAX25((ether_t *)&(e_arp->thwaddr[0]), &(a_arp->thwaddr[0]));
  177.     else {
  178.         for( i = 0; i < AXALEN; i++)
  179.             a_arp->thwaddr[i] = '\0';
  180.     }
  181.     a_arp->tprotoaddr = e_arp->tprotoaddr;
  182. }
  183.  
  184. /* Convert a pseudo-Ethernet address to an AX.25 address in network form */
  185. void
  186. EtherToAX25(ether_t *ether, unsigned char *ax25)
  187. {
  188.     register int i;
  189.  
  190.     for (i = 0; i < PSEUDOLEN; i++) {
  191.         if( ether[i] != (unsigned char)0xff )
  192.             break;
  193.     }
  194.  
  195.     if( i == PSEUDOLEN ) {
  196.       for( i = 0; i < AXALEN; i++)
  197.     *ax25++ = qst[i];
  198.       return;
  199.     }
  200.     
  201.     ax25[0] = ether[1];
  202.     ax25[1] = ether[2];
  203.     ax25[2] = eightbit[ ether[3] >> 2 ];
  204.     ax25[3] = eightbit[ ((ether[3] & 0x3) << 4) | (ether[4] >> 4) ];
  205.     ax25[4] = eightbit[ ((ether[4] & 0xf ) << 2) | (ether[5] >> 6) ];
  206.     ax25[5] = eightbit[ ether[5] & 0x3f ];
  207.     ax25[6] = ether[0];
  208. }
  209.  
  210. #ifndef DRIVER
  211.  
  212. /* Convert an AX.25 address in null terminated string into network form */
  213.  
  214. void
  215. StrToAX25(char *s, unsigned char *ax25)
  216. {
  217.  
  218.     unsigned char *axp = &ax25[0];
  219.  
  220.     while(*s != '\0' && *s != '-') {
  221.         *axp++ = toupper(*s) << 1;
  222.         s++;
  223.     }
  224.  
  225.     while( axp < &ax25[6] )
  226.         *axp++ = ' ' << 1;
  227.             
  228.     if( *s++ == '-')
  229.         *axp = atoi(s) << 1;
  230.     else
  231.         *axp = '\0';
  232.  
  233. }
  234.  
  235. /* Convert an AX.25 address in network form into a null terminated string */
  236. void
  237. AX25ToStr(unsigned char *ax25, char *s)
  238. {
  239.     int i;
  240.  
  241.     for( i = 0; i < 6; i++) {
  242.         if( (*ax25 >> 1) != ' ')
  243.             *s++ = *ax25 >> 1;
  244.         ax25++;
  245.     }
  246.     if( *ax25 != '\0' ) {
  247.         *s++ = '-';
  248.         (void)itoa(*ax25 >> 1, s, 10);
  249.     } else
  250.         *s = '\0';
  251. }
  252. #endif
  253.  
  254. #undef TEST
  255. #ifdef TEST
  256. #include <stdio.h>
  257.  
  258. main(int argc, char **argv)
  259. {
  260.     char c;
  261.     unsigned char ax25[7];
  262.     unsigned char ether[6];
  263.     char callsign[8];
  264.     int i;
  265.  
  266.     while( 1 ) {
  267.     printf("[A]X.25 or [E]thernet?: ");
  268.     scanf(" %c", &c);
  269.  
  270.     if( c == 'A' ) {
  271.  
  272.         /* Pervert the callsign into AX.25 form including shift */
  273.         scanf(" %s", callsign);
  274.             StrToAX25(callsign, ax25);
  275.  
  276.         /* Translate, and translate back */
  277.         AX25ToEther(ax25, ether);
  278.         for( i = 0; i < 5; i++)
  279.         printf("%02x-", ether[i]);
  280.         printf("%02x\n", ether[5]);
  281.  
  282.         EtherToAX25(ether, ax25);
  283.             AX25ToStr(ax25, callsign);
  284.             printf("%s\n", callsign);
  285.  
  286.     } else {
  287.  
  288.         scanf(" %x-%x-%x-%x-%x-%x", ðer[0], ðer[1], ðer[2],
  289.           ðer[3], ðer[4], ðer[5]);
  290.  
  291.         /* Translate, and translate back */
  292.         EtherToAX25(ether, ax25);
  293.         for(i = 0; i < 6; i++)
  294.         printf("%c", ax25[i]>>1);
  295.         printf("-%d\n", ax25[6]>>1);
  296.  
  297.         AX25ToEther(ax25, ether);
  298.         for( i = 0; i < 5; i++)
  299.         printf("%02x-", ether[i]);
  300.         printf("%02x\n", ether[5]);
  301.  
  302.     }
  303.     }
  304. }
  305. #endif
  306.